#include "dds_ctl.h"
//#include <stdio.h>
#include <string.h>

PACDAT pacdat;
PACDAT pacdatRead;

FIL waveFile;
extern FATFS fs;
extern DIR dirs;
extern unsigned int br;
extern char fatfr;

#define DDS_MAX_BUF		4096
#define DDS_MAX_RES		8

#define userDefineWavePath "0:_wave/"
#define SIN_FILE_NAME				"_default/SIN.WDA"
#define TRI_FILE_NAME				"_default/TRI.WDA"
#define SAW_FILE_NAME				"_default/SAW.WDA"
#define SQA_FILE_NAME				"_default/SQA.WDA"

void pacInit(void)
{
	pacFileRead(pacdatRead.transfer);
}

void updateWaveFile(char *fileName)
{
	int i;
	
	char waveFilePath[50] = userDefineWavePath;
	int waveResolution;	//waveResolution
	int wavePoints;			//waveSamplingPoints
	int waveDataBuff;
	unsigned char resOffset = 0;
	
	strcat(waveFilePath ,fileName);
	
	//printf("\r\nFile Name : %s",fileName);
	printf("\r\nFile Path : %s",waveFilePath);
	
	//open file
	USB_Interrupts_Disable();
	
	if((fatfr = f_open(&waveFile, waveFilePath , FA_OPEN_EXISTING | FA_READ)) == FR_OK)
	{
		f_read(&waveFile,&waveResolution,4,&br);
		f_read(&waveFile,&wavePoints,4,&br);
		printf("\r\nwaveResolution:%d  waveSamplingPoints:%d",waveResolution,wavePoints);
		
		printf("\r\nSending Wave Data to DDS ... ");
		
		if(waveResolution > DDS_MAX_RES)
			resOffset = waveResolution - DDS_MAX_RES;
		else
			resOffset = 0;
		
		if(wavePoints > DDS_MAX_BUF)
			wavePoints = DDS_MAX_BUF;
		fpgaWriteCMD(SET_BUF_SIZE);
		//fpgaWriteCMD(SET_BUF_SIZE);
		fpgaWriteDAT((uint16_t)(wavePoints & 0xffff));
		fpgaWriteCMD(WR_FULL_DAT);
		//fpgaWriteCMD(WR_FULL_DAT);
		for(i=0 ; i<wavePoints ; i++)
		{
			f_read(&waveFile,&waveDataBuff,4,&br);
			fpgaWriteDAT((uint16_t)((waveDataBuff & 0xffff) >> resOffset));
		}
		printf("OK");
	}
	else
	{
		printf("\r\nOpen Wave File Error!");
	}
	
	f_close(&waveFile);
	
	USB_Interrupts_Enable();
}

int pacUpdate(void)
{
	int changeState = 0;
	pacFileRead(pacdatRead.transfer);
	
	/*print reading data*/
	/*printf("PAC Read\n");
	printf("wave select: %d\n",pacdat.ctl.wave_select);
	printf("frequence: %ld\n",pacdat.ctl.frequence);
	printf("buffer_len: %ld\n",pacdat.ctl.buffer_len);
	printf("vpp: %ld\n",pacdat.ctl.vpp);
	printf("offset: %ld\n",pacdat.ctl.offset);*/
	
	if( (changeState = pacIsChanged()) != 0 ) //pac is changed
	{
		printf("\r\nUpdate parameter to FPGA %x",changeState);
		
		//copy data
		pacdat.ctl.wave_select = pacdatRead.ctl.wave_select;
		pacdat.ctl.frequence = pacdatRead.ctl.frequence;
		//pacdat.ctl.buffer_len = pacdatRead.ctl.buffer_len;
		pacdat.ctl.vpp = pacdatRead.ctl.vpp;
		pacdat.ctl.offset = pacdatRead.ctl.offset;
		
		//update parameter to fpga
		fpgaWriteCMD(DDS_PAUSE);
		fpgaWriteCMD(SET_FRE_PARA);
		fpgaWriteDAT((uint16_t)(pacdat.ctl.frequence & 0xffff));					//write lower 16bits
		fpgaWriteDAT((uint16_t)((pacdat.ctl.frequence >> 16) & 0xffff));	//write higher 16bits
		//fpgaWriteCMD(SET_BUF_SIZE);
		//fpgaWriteDAT(pacdat.ctl.buffer_len);
		
		
		//check if there's need to change the wave
		//if( (changeState & 0x01) || ((pacdatRead.ctl.wave_select == 0)&&(changeState & 0x100)) )
		if( (changeState & 0x01) || (changeState & 0x100) )
		{
			pacdat.ctl.wave_select = pacdatRead.ctl.wave_select;
			printf("\r\nUpdate Wave File ...");
			switch(pacdat.ctl.wave_select)
			{
				case 0:
				{
					//user defined wave
					printf("\r\nUser Defined Wave");
					strcpy(pacdat.ctl.filename,pacdatRead.ctl.filename);
					updateWaveFile(pacdat.ctl.filename);
					break;
				}
				case 1:
				{
					printf("\r\nSin Wave");
					updateWaveFile(SIN_FILE_NAME);
					break;
				}
				case 2:
				{
					printf("\r\nTriangular Wave");
					updateWaveFile(TRI_FILE_NAME);
					break;
				}
				case 3:
				{
					printf("\r\nSawtooth Wave");
					updateWaveFile(SAW_FILE_NAME);
					break;
				}
				case 4:
				{
					printf("\r\nSquare Wave");
					updateWaveFile(SQA_FILE_NAME);
					break;
				}
				default:
				{
					printf("\r\nWrong Wave Select");
				}
			}
		}
		
		//delay_us(1);
		fpgaWriteCMD(DDS_ENABLE);
		delay_us(1);
		//fpgaWriteCMD(DDS_ENABLE);
		
		//update vpp & offset
		//SPI_DACSendData(VPP_INIT_VAL,OFFSET_INIT_VAL);
		SPI_DACSendData((uint16_t)(((double)pacdat.ctl.vpp / 100.0) * 4096),
										(uint16_t)(((double)pacdat.ctl.offset / 100.0) * 4096));
		//I2S_DACSendData((uint32_t)(((double)pacdat.ctl.vpp / 100.0) * 16777215),(uint32_t)(((double)pacdat.ctl.offset / 100.0) * 16777215));
		//DDS_SetVpp((uint32_t)(((double)pacdat.ctl.vpp / 100.0) * 16777215));
		//DDS_SetOffset((uint32_t)(((double)pacdat.ctl.offset / 100.0) * 16777215));
		
		printf("\r\nFre: %lx",pacdat.ctl.frequence);
		printf("\r\nVpp: %lx  Offset: %lx",(uint32_t)(((double)pacdat.ctl.vpp / 100.0) * 16777215),(uint32_t)(((double)pacdat.ctl.offset / 100.0) * 16777215));
		printf("\r\n%d %d",pacdat.ctl.vpp,pacdat.ctl.offset);
	}
	return 0;
}

int pacIsChanged(void)
{
	int pacResult = 0;
	
	if(pacdat.transfer != pacdatRead.transfer)
	{
		//printf("\r\n %d %d",pacdat.ctl.wave_select,pacdatRead.ctl.wave_select);
		if( pacdat.ctl.wave_select != pacdatRead.ctl.wave_select )
			pacResult |= 0x01;
		if( pacdat.ctl.frequence != pacdatRead.ctl.frequence )
			pacResult |= 0x02;
		//if( pacdat.ctl.buffer_len != pacdatRead.ctl.buffer_len )
		//	pacResult |= 0x04;
		if( pacdat.ctl.vpp != pacdatRead.ctl.vpp )
			pacResult |= 0x08;
		if( pacdat.ctl.offset != pacdatRead.ctl.offset )
			pacResult |= 0x10;
		if(strcmp(pacdat.ctl.filename,pacdatRead.ctl.filename))
			pacResult |= 0x100;
	}
	
	return pacResult;
	
}

//updata parameter to FPGA
void updateParaToFPGA( PACDAT pacdat )
{
	return;
}

void FPGA_Init(void)
{
	//update parameter to fpga
	fpgaWriteCMD(DDS_PAUSE);
//	fpgaWriteCMD(SET_FRE_RANGE);
//	fpgaWriteDAT(2);
	fpgaWriteCMD(SET_FRE_PARA);
	fpgaWriteDAT(0xff);
	fpgaWriteDAT(0xff);
	fpgaWriteCMD(SET_BUF_SIZE);
	fpgaWriteDAT(64);
	delay_us(1);
	fpgaWriteCMD(DDS_ENABLE);
	delay_us(1);
	fpgaWriteCMD(DDS_ENABLE);
	//update vpp & offset
	
	//I2S_DACSendData((uint32_t)(((double)pacdat.ctl.vpp / 100.0) * 16777215),(uint32_t)(((double)pacdat.ctl.offset / 100.0) * 16777215));
	//DDS_SetVpp(pacdat.ctl.vpp);
	//DDS_SetOffset(pacdat.ctl.offset);
}

